package com.qsw.extendedittext.view;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.text.Editable;
import android.text.InputFilter;
import android.text.InputType;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.text.method.DigitsKeyListener;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.qsw.extendedittext.R;
import com.qsw.extendedittext.util.EETUtils;
import com.qsw.extendedittext.view.listener.OnInputCheckSuccessListener;

import java.util.ArrayList;
import java.util.List;

/**
 * 支持分隔框的EditView
 */
public class DivideEditView extends FrameLayout {

    public static final int TYPE_CUSTOM = 0;    // 类型：自定义
    public static final int TYPE_PHONE = 1;     // 类型：手机号
    public static final int TYPE_BANKCARD = 2;  // 类型：银行卡号
    public static final int TYPE_IDCARD = 3;    // 类型：身份证号
    public static final int TYPE_ISBN = 4;      // 类型：书籍ISBN

    private int mMaxLength = 20;// 支持输入的最大字符
    private int mContentType;// 输入类型

    private String mFormatStr;// 格式字符串

    private final List<Integer> mDivideIndexList = new ArrayList<>();// 需要添加分隔符的索引，在该索引对应的字符后边添加一个分隔符，该索引为不包含分隔符的原始字符串索引值
    private final List<TextView> mTextViewList = new ArrayList<>();// TextView列表

    private EditText mEt;
    private String mEtDigits;

    private OnInputCheckSuccessListener mOnInputCheckSuccessListener;

    private int mStrokeWidth = 1;// 线宽，dp
    private int mStrokeColor = Color.BLACK;// 线颜色
    private int mSolidColor = Color.TRANSPARENT;// 填充色
    private int mRadius = 0;// 圆角弧度
    private int mTextSize = 15;  // 字体大小，sp
    private int mTextColor = Color.BLACK;// 字体颜色

    private int mDivideWidth = 5;// 边框之间的间距，单位：dp

    public DivideEditView(Context context) {
        this(context, null);
    }

    public DivideEditView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public DivideEditView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        parseAttributeSet(context, attrs);
    }

    /**
     * 解析xml属性
     *
     * @param context 环境
     * @param attrs   属性集
     */
    private void parseAttributeSet(Context context, AttributeSet attrs) {
        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.DivideEditView, 0, 0);
        mContentType = typedArray.getInt(R.styleable.DivideEditView_edit_type, 0);
        mFormatStr = typedArray.getString(R.styleable.DivideEditView_edit_format);
        String textStr = typedArray.getString(R.styleable.DivideEditView_edit_text);
        typedArray.recycle();

        initContentType();

        setText(textStr);
    }

    /**
     * 解析格式
     *
     * @param formatStr 格式字符串
     */
    private void parseFormat(String formatStr) {
        // 格式中的分隔符
        if (TextUtils.isEmpty(formatStr)) {
            return;
        }
        StringBuilder sbFormat = new StringBuilder(formatStr);
        char formatDivide = '*';
        while (sbFormat.charAt(0) == formatDivide) {
            sbFormat.delete(0, 1);
            if (sbFormat.length() == 0) {
                return;
            }
        }
        while (sbFormat.charAt(sbFormat.length() - 1) == formatDivide) {
            sbFormat.delete(sbFormat.length() - 1, sbFormat.length());
            if (sbFormat.length() == 0) {
                return;
            }
        }

        int divideCount = 0;
        mDivideIndexList.clear();
        for (int i = 0; i < sbFormat.length(); i++) {
            if (sbFormat.charAt(i) == formatDivide) {
                mDivideIndexList.add(i - 1 - divideCount);
                divideCount++;
            }
        }
        mMaxLength = sbFormat.length() - divideCount;
    }

    /**
     * 初始化输入类型
     */
    private void initContentType() {
        removeAllViews();
        mTextViewList.clear();
        mEtDigits = null;
        mEt = null;
        if (mContentType == TYPE_CUSTOM) {
            parseFormat(mFormatStr);
            mEtDigits = "0123456789ABCDEFGHIGKLMNOPQRSTUVWXYZabcdefghigklmnopqrstuvwxyz";
            mEt = new FixCursorEditText(getContext());
            mEt.setInputType(InputType.TYPE_CLASS_TEXT);
        } else if (mContentType == TYPE_PHONE) {
            mMaxLength = 11;
            mEtDigits = "0123456789";
            mDivideIndexList.clear();
            mDivideIndexList.add(2);
            mDivideIndexList.add(6);
            mEt = new FixCursorEditText(getContext());
            mEt.setInputType(InputType.TYPE_CLASS_NUMBER);
        } else if (mContentType == TYPE_BANKCARD) {
            mMaxLength = 19;
            mEtDigits = "0123456789";
            mDivideIndexList.clear();
            mDivideIndexList.add(3);
            mDivideIndexList.add(7);
            mDivideIndexList.add(11);
            mDivideIndexList.add(15);
            mEt = new FixCursorEditText(getContext());
            mEt.setInputType(InputType.TYPE_CLASS_NUMBER);
        } else if (mContentType == TYPE_IDCARD) {
            mMaxLength = 18;
            mEtDigits = "0123456789xX";
            mDivideIndexList.clear();
            mDivideIndexList.add(5);
            mDivideIndexList.add(9);
            mDivideIndexList.add(13);
            mEt = new FixCursorEditText(getContext());
            mEt.setInputType(InputType.TYPE_CLASS_TEXT);
        } else if (mContentType == TYPE_ISBN) {
            // 000*0*0000*0000*0
            // 图书类代码-地区代码-出版社-书序码-校验码
            mMaxLength = 13;
            mEtDigits = "0123456789";
            mDivideIndexList.clear();
            mDivideIndexList.add(2);
            mDivideIndexList.add(3);
            mDivideIndexList.add(7);
            mDivideIndexList.add(11);
            mDivideIndexList.add(12);
            mEt = new FixCursorEditText(getContext());
            mEt.setInputType(InputType.TYPE_CLASS_NUMBER);
        }

        for (int i = 0; i < mDivideIndexList.size() + 1; i++) {
            TextView textView = new TextView(getContext());
            mTextViewList.add(textView);
        }

        // setKeyListener要在setInputType后面调用，否则无效
        if (mEt != null) {
            mEt.setBackground(null);
            mEt.setCursorVisible(false);
            mEt.setTextSize(0);
            if (mEtDigits != null) {
                mEt.setKeyListener(DigitsKeyListener.getInstance(mEtDigits));
            }
            mEt.setSingleLine();
            mEt.addTextChangedListener(mTextWatcher);
            mEt.setFilters(new InputFilter[]{new InputFilter.LengthFilter(mMaxLength)});
            addView(mEt);
            ViewGroup.LayoutParams etLayoutParams = mEt.getLayoutParams();
            etLayoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
            etLayoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
        }

        LinearLayout linearLayout = new LinearLayout(getContext());
        linearLayout.setOrientation(LinearLayout.HORIZONTAL);
        addView(linearLayout);
        ViewGroup.LayoutParams llLayoutParams = linearLayout.getLayoutParams();
        llLayoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT;
        llLayoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT;
        int lastIndex = -1;
        for (int i = 0; i < mTextViewList.size(); i++) {
            mTextViewList.get(i).setGravity(Gravity.CENTER);
            linearLayout.addView(mTextViewList.get(i));
            LinearLayout.LayoutParams tvLayoutParams;
            if (i < mDivideIndexList.size()) {
                tvLayoutParams = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT,
                        mDivideIndexList.get(i) - lastIndex);
                lastIndex = mDivideIndexList.get(i);
            } else {
                tvLayoutParams = new LinearLayout.LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT,
                        mMaxLength - lastIndex - 1);
            }
            mTextViewList.get(i).setLayoutParams(tvLayoutParams);
            refreshTextView(mTextViewList.get(i));
        }
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        mEt.requestFocus();
        InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
        imm.showSoftInput(mEt, InputMethodManager.SHOW_FORCED);
        return true;
    }

    /**
     * 设置边框线宽
     *
     * @param strokeWidth 边框线宽，单位：dp
     */
    public void setStrokeWidth(int strokeWidth) {
        this.mStrokeWidth = strokeWidth;
        refreshAllTextView();
    }

    /**
     * 设置边框颜色
     *
     * @param strokeColor 边框颜色
     */
    public void setStrokeColor(int strokeColor) {
        this.mStrokeColor = strokeColor;
        refreshAllTextView();
    }

    /**
     * 设置填充色
     *
     * @param solidColor 填充色
     */
    public void setSolidColor(int solidColor) {
        this.mSolidColor = solidColor;
        refreshAllTextView();
    }

    /**
     * 设置边框弧度
     *
     * @param radius 边框弧度，单位：dp
     */
    public void setRadius(int radius) {
        this.mRadius = radius;
        refreshAllTextView();
    }

    /**
     * 设置文字大小
     *
     * @param textSize 文字大小，单位：sp
     */
    public void setTextSize(int textSize) {
        this.mTextSize = textSize;
        refreshAllTextView();
    }

    /**
     * 设置文字颜色
     *
     * @param textColor 文字颜色
     */
    public void setTextColor(int textColor) {
        this.mTextColor = textColor;
        refreshAllTextView();
    }

    /**
     * 设置边框之间的间距
     *
     * @param divideWidth 边框之间的间距，，单位：dp
     */
    public void setDivideWidth(int divideWidth) {
        this.mDivideWidth = divideWidth;
        refreshAllTextView();
    }

    /**
     * 刷新所有TextView设置
     */
    private void refreshAllTextView() {
        for (int i = 0; i < mTextViewList.size(); i++) {
            refreshTextView(mTextViewList.get(i));
        }
    }

    /**
     * 刷新指定TextView设置
     */
    private void refreshTextView(TextView textView) {
        textView.setBackground(EETUtils.getShapeDrawable(mSolidColor,
                mStrokeColor, EETUtils.dp2px(getContext(), mStrokeWidth),
                0, 0, EETUtils.dp2px(getContext(), mRadius)));
        textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, mTextSize);
        textView.setTextColor(mTextColor);
        if (mTextViewList.indexOf(textView) != 0) {
            ((LinearLayout.LayoutParams) textView.getLayoutParams())
                    .setMargins(EETUtils.dp2px(getContext(), mDivideWidth), 0, 0, 0);
        }
    }

    /**
     * 获取所有EditText拼接成的字符串
     *
     * @return 所有EditText拼接成的字符串
     */
    public String getTextWithoutDivide() {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < mTextViewList.size(); i++) {
            String text = mTextViewList.get(i).getText().toString();
            if (!TextUtils.isEmpty(text)) {
                sb.append(text);
            }
        }
        return sb.toString();
    }

    /**
     * 设置Text
     *
     * @param str Text
     */
    public void setText(String str) {
        if (mEt != null) {
            StringBuilder sb = new StringBuilder();
            if (str != null) {
                for (int i = 0; i < str.length(); i++) {
                    if (mEtDigits.contains(String.valueOf(str.charAt(i)))) {
                        sb.append(str.charAt(i));
                    }
                }
            }
            mEt.setText(sb.toString());
        }
    }

    /**
     * 判断当前文本是否符合规则
     *
     * @return true：符合；false：不符合
     */
    public boolean isContentCheck() {
        String withoutDivideStr = getTextWithoutDivide();
        return !TextUtils.isEmpty(withoutDivideStr) && withoutDivideStr.length() == mMaxLength;
    }

    private final TextWatcher mTextWatcher = new TextWatcher() {
        @Override
        public void beforeTextChanged(CharSequence s, int start, int count, int after) {
        }

        @Override
        public void onTextChanged(CharSequence s, int start, int before, int count) {
        }

        @Override
        public void afterTextChanged(Editable s) {
            for (TextView textView : mTextViewList) {
                textView.setText("");
            }
            int tvIndex = 0;
            int start = 0;
            for (int i = 0; i <= s.length(); i++) {
                mTextViewList.get(tvIndex).setText(s.subSequence(start, i));
                if (tvIndex < mDivideIndexList.size() && i > mDivideIndexList.get(tvIndex)) {
                    start = i;
                    tvIndex++;
                }
            }

            if (isContentCheck() && mOnInputCheckSuccessListener != null) {
                mOnInputCheckSuccessListener.onInputCheckSuccess(getTextWithoutDivide());
            }
        }
    };

    public void setOnInputCheckSuccessListener(OnInputCheckSuccessListener onInputCheckSuccessListener) {
        mOnInputCheckSuccessListener = onInputCheckSuccessListener;
    }
}
